package org.naughtybabystudio.android.crazydriver.bluetoothSppManager;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;

import org.naughtybabystudio.android.crazydriver.R;
import org.naughtybabystudio.android.crazydriver.WelcomeActivity;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Handler;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

public class BluetoothSppManager {
	
	private Context mContext=null;
	private BluetoothAdapter mCommAdapter=null;
	private int mPreviousBluetoothEnabled;
	
	private Handler mHandler=new Handler();
	
	static final String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";
	private BluetoothSocket mBtSocket=null;
//	private ToyVehicle mVehicle=new ToyVehicle();
	
	SharedPreferences mSettings=null;

	public BluetoothSppManager(Context context) {
		super();
		mContext=context;
		init();
	}
	
	private boolean init() {
		mCommAdapter=BluetoothAdapter.getDefaultAdapter();
		if( mCommAdapter==null ) {
			new AlertDialog.Builder(mContext).setTitle("Error").setMessage("Bluetooth is not available on this device.").show();
			return false;
		}
		mPreviousBluetoothEnabled=mCommAdapter.getState();
		mSettings=mContext.getSharedPreferences(this.getClass().getName(), 0);
		return true;
	}
	
	private boolean isValid() {
		if( mContext==null ) return false;
		if( mCommAdapter==null ) return false;
		return true;
	}
	
	public boolean connect() {
		if( !isValid() ) return false;
		
		if(mBtSocket!=null) {
			try {
				mBtSocket.close();
			} catch (IOException e) {
				Toast.makeText(mContext, "Failed to close current connection", 1000).show();
				return false;
			}
		}
		
		final BluetoothDeviceSelectDialog dialog=new BluetoothDeviceSelectDialog(
				mContext,
				new BluetoothDeviceSelectDialogListener() {

					@Override
					public void onDeviceSelected(String strDeviceAddr) {
						
						final ProgressDialog processdialog=ProgressDialog.show(mContext, null, "Connecting...",true,false);
						final String strAddr=strDeviceAddr;
						new Thread() {
							public void run() {
								UUID uuid = UUID.fromString(SPP_UUID);
								final BluetoothDevice device=BluetoothAdapter.getDefaultAdapter().getRemoteDevice(strAddr);
								if(device==null) {
									mHandler.post(new Runnable() {
										@Override
										public void run() {
											Toast.makeText(mContext, "Device not available", 1000).show();
										}
									});
								}
								try {
									if(true) {
										mBtSocket = device.createRfcommSocketToServiceRecord(uuid);	
									}
									else {
										BluetoothDevice hxm = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(device.getAddress());
										Method m;
										m = device.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
										mBtSocket = (BluetoothSocket)m.invoke(hxm, Integer.valueOf(1));
									}
									mBtSocket.connect();
									mSettings.edit().putString(device.getAddress(), device.getName()).commit();
								} catch (IOException e) {
									mHandler.post(new Runnable() {
										@Override
										public void run() {
											Toast.makeText(mContext, "Failed to create SPP connection to "+device.getName(), 1000).show();
										}
									});
									mBtSocket=null;
									mSettings.edit().remove(device.getAddress()).commit();
								} catch (IllegalArgumentException e) {
									mHandler.post(new Runnable() {
										@Override
										public void run() {
											Toast.makeText(mContext, "Failed to create SPP connection to "+device.getName(), 1000).show();
										}
									});
									mBtSocket=null;
									mSettings.edit().remove(device.getAddress()).commit();
								} catch (IllegalAccessException e) {
									mHandler.post(new Runnable() {
										@Override
										public void run() {
											Toast.makeText(mContext, "Failed to create SPP connection to "+device.getName(), 1000).show();
										}
									});
									mBtSocket=null;
									mSettings.edit().remove(device.getAddress()).commit();
								} catch (InvocationTargetException e) {
									mHandler.post(new Runnable() {
										@Override
										public void run() {
											Toast.makeText(mContext, "Failed to create SPP connection to "+device.getName(), 1000).show();
										}
									});
									mBtSocket=null;
									mSettings.edit().remove(device.getAddress()).commit();
								} catch (SecurityException e) {
									mHandler.post(new Runnable() {
										@Override
										public void run() {
											Toast.makeText(mContext, "Failed to create SPP connection to "+device.getName(), 1000).show();
										}
									});
									mBtSocket=null;
									mSettings.edit().remove(device.getAddress()).commit();
								} catch (NoSuchMethodException e) {
									mHandler.post(new Runnable() {
										@Override
										public void run() {
											Toast.makeText(mContext, "Failed to create SPP connection to "+device.getName(), 1000).show();
										}
									});
									mBtSocket=null;
									mSettings.edit().remove(device.getAddress()).commit();
								}
								processdialog.dismiss();
							}
						}.start();
					}
			
				});
		Map<String, ?> storedDevices=mSettings.getAll();
		Iterator it=storedDevices.entrySet().iterator();
		while(it.hasNext()) {
			Map.Entry entry=(Map.Entry)it.next();
			Object key=entry.getKey();
			Object val=entry.getValue();
			if( key instanceof String && val instanceof String ) {
				dialog.addDevice((String)key, (String)val);
			}
		}
		dialog.setFilter(".*");
		dialog.show();
		
		return true;
	}
	
	public boolean canSppWork() {
		if(mBtSocket!=null) {
			try {
				if(mBtSocket.getOutputStream()!=null) {
					return true;
				}
			} catch (IOException e) {
			}
		}
		return false;
	}
	
	public void writeStream(byte[] bytes) throws IOException {
		OutputStream out=mBtSocket.getOutputStream();
		out.write(bytes);
	}
	
	public void readStream(byte[] bytes) throws IOException {
		InputStream in=mBtSocket.getInputStream();
		in.read(bytes);
	}
	
	public void restorePreviousBtState() {
		if(mPreviousBluetoothEnabled==BluetoothAdapter.STATE_TURNING_OFF
			|| mPreviousBluetoothEnabled==BluetoothAdapter.STATE_OFF) {
			mCommAdapter.disable();
		}
	}
}
